package com.htdata.iiot.api.tsdb.utils;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import net.opentsdb.core.TSQuery;
import net.opentsdb.core.TSSubQuery;
import net.opentsdb.query.filter.TagVFilter;

/**
 * Builder class help to build TSQuery for query opentsdb data
 * 
 * @author shanyou
 *
 */
public class TSQueryBuilder {
	private SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
	private Date startTime;
	private Date endTime;
	private String metricName;
	private String aggregator;
	private String filterType;
	private boolean groupBy;
	private boolean msResolution;
	private String downsample;

	private Map<String, String> tags;

	public Date getStartTime() {
		return startTime;
	}

	public TSQueryBuilder setStartTime(Date startTime) {
		this.startTime = startTime;
		return this;
	}

	public Date getEndTime() {
		return endTime;
	}

	public TSQueryBuilder setEndTime(Date endTime) {
		this.endTime = endTime;
		return this;
	}

	public String getMetricName() {
		return metricName;
	}

	public TSQueryBuilder setMetricName(String metricName) {
		this.metricName = metricName;
		return this;
	}

	public String getAggregator() {
		return aggregator;
	}

	public TSQueryBuilder setAggregator(String aggregator) {
		this.aggregator = aggregator;
		return this;
	}

	public String getFilterType() {
		return filterType;
	}

	public TSQueryBuilder setFilterType(String filterType) {
		this.filterType = filterType;
		return this;
	}

	public TSQueryBuilder setFilterTag(String tagK, String tagV) {
		this.tags.put(tagK, tagV);
		return this;
	}

	public boolean isGroupBy() {
		return groupBy;
	}

	public TSQueryBuilder setGroupBy(boolean groupBy) {
		this.groupBy = groupBy;
		return this;
	}

	public boolean isMsResolution() {
		return msResolution;
	}

	public TSQueryBuilder setMsResolution(boolean msResolution) {
		this.msResolution = msResolution;
		return this;
	}

	public String getDownsample() {
		return downsample;
	}

	public TSQueryBuilder setDownsample(String downsample) {
		this.downsample = downsample;
		return this;
	}

	public TSQueryBuilder() {
		initDefaultValues();
	}

	private void initDefaultValues() {
		this.aggregator = "avg";
		this.filterType = "literal_or";
		this.metricName = "*";
		this.tags = new HashMap<>();
		this.groupBy = false;
		this.msResolution = true;

	}

	/**
	 * build tsquery class
	 * 
	 * @return {@link TSQuery}
	 */
	public TSQuery build() {
		TSQuery tsQuery = new TSQuery();
		tsQuery.setStart(dateFormat.format(this.startTime));
		tsQuery.setEnd(dateFormat.format(this.endTime));
		tsQuery.setMsResolution(this.msResolution);

		TSSubQuery subQuery = new TSSubQuery();
		subQuery.setMetric(this.metricName);
		subQuery.setAggregator(this.aggregator);
		subQuery.setDownsample(downsample);
		int tagVSize = this.tags.size();
		List<TagVFilter> filters = new ArrayList<TagVFilter>(tagVSize);
		for (Entry<String, String> tag : tags.entrySet()) {
			filters.add(new TagVFilter.Builder().setType(this.filterType).setFilter(tag.getValue())
					.setTagk(tag.getKey()).setGroupBy(this.groupBy).build());
		}
		subQuery.setFilters(filters);

		if (downsample!=null&&!downsample.isEmpty()/*StringUtils.isNotEmpty(downsample)*/) {
			subQuery.setDownsample(this.downsample);
		}

		ArrayList<TSSubQuery> subQueries = new ArrayList<TSSubQuery>(1);
		subQueries.add(subQuery);
		tsQuery.setQueries(subQueries);

		try {
			tsQuery.validateAndSetQuery();
		} catch (Exception ex) {
			throw new RuntimeException("error valid and set query", ex);
		}
		return tsQuery;
	}
}
